home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / upc12bs1.zip / UUCICO / dcpsys.c < prev    next >
C/C++ Source or Header  |  1993-10-03  |  37KB  |  1,024 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    d c p s y s . c                                                 */
  3. /*                                                                    */
  4. /*    System support functions for UUCICO                             */
  5. /*                                                                    */
  6. /*    Changes Copyright (c) 1990-1993 by Kendra Electronic            */
  7. /*    Wonderworks.                                                    */
  8. /*                                                                    */
  9. /*    Changes Copyright (c) 1989 by Andrew H. Derbyshire.             */
  10. /*                                                                    */
  11. /*    All rights reserved except those explicitly granted by the      */
  12. /*    UUPC/extended license agreement.                                */
  13. /*                                                                    */
  14. /*    Copyright (c) Richard H. Lamb 1985, 1986, 1987                  */
  15. /*    Changes Copyright (c) Stuart Lynne 1987                         */
  16. /*                                                                    */
  17. /* Updated:                                                           */
  18. /*                                                                    */
  19. /*    13May89  - Modified checkname to only examine first token of    */
  20. /*               name.                                                */
  21. /*               Modified rmsg to initialize input character before   */
  22. /*               use.                                                 */
  23. /*    16May89  - Moved checkname to router.c - ahd                    */
  24. /*    17May89  - Wrote real checktime() - ahd                         */
  25. /*    17May89  - Changed getsystem to return 'I' instead of 'G'       */
  26. /*    25Jun89  - Added Reach-Out America to keyword table for         */
  27. /*               checktime                                            */
  28. /*    22Sep89  - Password file support for hosts                      */
  29. /*    25Sep89  - Change 'ExpectStr' message to debuglevel 2           */
  30. /*    01Jan90  - Revert 'ExpectStr' message to debuglevel 1           */
  31. /*    28Jan90  - Alter callup() to use table driven modem driver.     */
  32. /*               Add direct(), qx() procedures.                       */
  33. /*    8 Jul90  - Add John DuBois's expectstr() routine to fix         */
  34. /*               problems with long input buffers.                    */
  35. /*    11Nov90  - Delete QX support, add ddelay, ssleep calls          */
  36. /*    21Sep92  - Insure system system name and time do not crash      */
  37. /*               UUCICO - from the original fix by Eugene             */
  38. /*               Nesterenko, Moscow, Russia                           */
  39. /*--------------------------------------------------------------------*/
  40.  
  41. /*
  42.  *     $Id: dcpsys.c 1.24 1993/10/03 22:34:33 ahd Exp $
  43.  *
  44.  *     $Log: dcpsys.c $
  45.  * Revision 1.24  1993/10/03  22:34:33  ahd
  46.  * Alter format of numbers printed
  47.  *
  48.  * Revision 1.23  1993/09/29  04:52:03  ahd
  49.  * Use additional state in support of suspend port code
  50.  *
  51.  * Revision 1.22  1993/09/28  01:38:19  ahd
  52.  * Add configurable timeout for conversation start up phase
  53.  *
  54.  * Revision 1.21  1993/09/27  04:04:06  ahd
  55.  * Normalize references to modem speed to avoid incorrect displays
  56.  *
  57.  * Revision 1.20  1993/09/27  00:48:43  ahd
  58.  * Allow 't' protocol under 16 bit OS/2
  59.  *
  60.  * Revision 1.19  1993/09/21  01:42:13  ahd
  61.  * Move declare of protocol list into source from header
  62.  *
  63.  * Revision 1.18  1993/09/20  04:48:25  ahd
  64.  * TCP/IP support from Dave Watt
  65.  * 't' protocol support
  66.  * OS/2 2.x support (BC++ 1.0 for OS/2)
  67.  *
  68.  * Revision 1.17  1993/08/26  05:00:25  ahd
  69.  * Debugging code for odd failures on J. McBride's network
  70.  *
  71.  * Revision 1.16  1993/05/30  00:01:47  ahd
  72.  * Multiple commuications drivers support
  73.  *
  74.  * Revision 1.15  1993/05/09  03:41:47  ahd
  75.  * Make wmsg accept const string
  76.  * Make sending/receiving of -x string to/from remote UUCICO optional
  77.  * Delete rejection of high levels of debug for anonymous UUCICO's
  78.  *
  79.  * Revision 1.14  1993/05/06  03:41:48  ahd
  80.  * Save true host name of caller in hostp->via field for use by
  81.  * SYSLOG processing.
  82.  *
  83.  * Revision 1.13  1993/04/11  00:34:11  ahd
  84.  * Global edits for year, TEXT, etc.
  85.  *
  86.  * Revision 1.12  1993/04/05  04:35:40  ahd
  87.  * Add timestamp, file size to directory information
  88.  *
  89.  * Revision 1.11  1993/01/23  19:08:09  ahd
  90.  * Don't update system stats in sysend()
  91.  *
  92.  * Revision 1.10  1992/12/11  12:45:11  ahd
  93.  * Shorten remote display to improve OS/2 windowed scrolling
  94.  *
  95.  * Revision 1.9  1992/12/01  04:37:03  ahd
  96.  * Modify *nbstime call restrictions to make it less agressive
  97.  *
  98.  * Revision 1.8  1992/11/22  21:20:45  ahd
  99.  * Use strpool for const string allocation
  100.  *
  101.  * Revision 1.7  1992/11/21  06:17:08  ahd
  102.  * Transmit only one character in response to P (protocol) request
  103.  *
  104.  * Revision 1.6  1992/11/19  03:00:51  ahd
  105.  * drop rcsid
  106.  *
  107.  * Revision 1.5  1992/11/18  03:49:21  ahd
  108.  * Move check of call window to avoid premature lock file overhead
  109.  *
  110.  * Revision 1.4  1992/11/17  13:46:42  ahd
  111.  * If host lookup fails, issue real error message, not malloc failure!
  112.  *
  113.  * Revision 1.3  1992/11/16  02:14:17  ahd
  114.  * Initialize previous directory scanned variable in scandir
  115.  *
  116.  * Revision 1.2  1992/11/15  20:11:07  ahd
  117.  * Clean up modem file support for different protocols
  118.  *
  119.  */
  120.  
  121. /*--------------------------------------------------------------------*/
  122. /*                        system include files                        */
  123. /*--------------------------------------------------------------------*/
  124.  
  125. #include <stdio.h>
  126. #include <stdlib.h>
  127. #include <string.h>
  128. #include <time.h>
  129. #include <ctype.h>
  130.  
  131. /*--------------------------------------------------------------------*/
  132. /*                    UUPC/extended include files                     */
  133. /*--------------------------------------------------------------------*/
  134.  
  135. #include "lib.h"
  136. #include "arpadate.h"
  137. #include "checktim.h"
  138. #include "dcp.h"
  139. #include "dcpfpkt.h"
  140. #include "dcpgpkt.h"
  141. #include "dcptpkt.h"
  142. #include "dcplib.h"
  143. #include "dcpsys.h"
  144. #include "export.h"
  145. #include "hlib.h"
  146. #include "hostable.h"
  147. #include "hostatus.h"
  148. #include "modem.h"
  149. #include "lock.h"
  150. #include "nbstime.h"
  151. #include "uundir.h"
  152. #include "ssleep.h"
  153. #include "security.h"
  154. #include "commlib.h"
  155.  
  156. currentfile();
  157.  
  158. /*--------------------------------------------------------------------*/
  159. /*                     Define available protocols                     */
  160. /*--------------------------------------------------------------------*/
  161.  
  162. typedef struct {
  163.         char type;
  164.         procref getpkt, sendpkt, openpk, closepk, rdmsg, wrmsg, eofpkt,
  165.                   filepkt;
  166.         boolean network;
  167. } Proto;
  168.  
  169. Proto Protolst[] = {
  170.        { 'g', ggetpkt, gsendpkt, gopenpk, gclosepk,
  171.               grdmsg,  gwrmsg,   geofpkt, gfilepkt,
  172.               FALSE,
  173.        } ,
  174.  
  175.        { 'G', ggetpkt, gsendpkt, Gopenpk, gclosepk,
  176.               grdmsg,  gwrmsg,   geofpkt, gfilepkt,
  177.               FALSE,
  178.        } ,
  179.  
  180.        { 'f', fgetpkt, fsendpkt, fopenpk, fclosepk,
  181.               frdmsg,  fwrmsg,   feofpkt, ffilepkt,
  182.               FALSE,
  183.        } ,
  184.  
  185.        { 'v', ggetpkt, gsendpkt, vopenpk, gclosepk,
  186.               grdmsg,  gwrmsg,   geofpkt, gfilepkt,
  187.               FALSE,
  188.        } ,
  189. #if defined(_Windows) || defined(BIT32ENV) || defined(FAMILYAPI)
  190.        { 't', tgetpkt, tsendpkt, topenpk, tclosepk,
  191.               grdmsg,  gwrmsg,   geofpkt, gfilepkt, // Yup, same as 'g'
  192.               TRUE,
  193.        } ,
  194. #endif
  195.    { '\0' }
  196.    };
  197.  
  198. procref  getpkt, sendpkt, openpk, closepk, rdmsg, wrmsg, eofpkt, filepkt;
  199.  
  200. char *flds[60];
  201. int kflds;
  202. static char protocols[5];
  203. static char S_sysline[BUFSIZ];
  204.  
  205. static void setproto(char wanted);
  206.  
  207. static char HostGrade( const char *fname, const char *remote );
  208.  
  209. /****************************************/
  210. /*              Sub Systems             */
  211. /****************************************/
  212.  
  213. /*--------------------------------------------------------------------*/
  214. /*    g e t s y s t e m                                               */
  215. /*                                                                    */
  216. /*    Process a systems file (L.sys) entry.                           */
  217. /*    Null lines or lines starting with '#' are comments.             */
  218. /*--------------------------------------------------------------------*/
  219.  
  220. CONN_STATE getsystem( const char sendgrade )
  221. {
  222.  
  223.    do {
  224.       char *p;
  225.  
  226.       /* flush to next non-comment line */
  227.       if (fgets(S_sysline, BUFSIZ, fsys) == nil(char))
  228.          return CONN_EXIT;
  229.  
  230.       p = S_sysline + strlen( S_sysline );
  231.  
  232. /*--------------------------------------------------------------------*/
  233. /*                     Trim trailing white space                      */
  234. /*--------------------------------------------------------------------*/
  235.  
  236.       while ((p-- > S_sysline) && isspace( *p ))
  237.          *p = '\0';
  238.  
  239.    } while ((*S_sysline == '\0') || (*S_sysline == '#'));
  240.  
  241.    printmsg(8, "sysline=\"%s\"", S_sysline);
  242.  
  243.    kflds = getargs(S_sysline, flds);
  244.  
  245. /*--------------------------------------------------------------------*/
  246. /*              Blitz all the extra fields we don't need              */
  247. /*--------------------------------------------------------------------*/
  248.  
  249.    if ( kflds < FLD_EXPECT )
  250.    {
  251.       printmsg(0,"getsystem:  Invalid system entry "
  252.                  "for %s (missing dial script)",
  253.             flds[FLD_REMOTE] );
  254.  
  255.       return CONN_INITIALIZE;
  256.    }
  257.  
  258.    strcpy(protocols, flds[FLD_PROTO]);
  259.    strcpy(rmtname, flds[FLD_REMOTE]);
  260.  
  261. /*--------------------------------------------------------------------*/
  262. /*                      Summarize the host data                       */
  263. /*--------------------------------------------------------------------*/
  264.  
  265.    printmsg(2,
  266.           "remote=%s, when=%s, device=%s, phone=%s, protocol=%s",
  267.           rmtname, flds[FLD_CCTIME], flds[FLD_TYPE], flds[FLD_PHONE],
  268.           protocols);
  269.  
  270. /*--------------------------------------------------------------------*/
  271. /*                  Determine if the remote is valid                  */
  272. /*--------------------------------------------------------------------*/
  273.  
  274.    hostp = checkreal( rmtname );
  275.    if ( hostp == NULL )
  276.    {
  277.       printmsg(0,"getsystem: Internal lookup error for system %s",
  278.                   rmtname);
  279.       panic();
  280.    }
  281.  
  282. /*--------------------------------------------------------------------*/
  283. /*                   Display the send/expect fields                   */
  284. /*--------------------------------------------------------------------*/
  285.  
  286.    if (debuglevel >= 4) {
  287.       int   i;
  288.       flds[ kflds ] = "";     /* Insure valid send string            */
  289.  
  290.       for (i = FLD_EXPECT; i < kflds; i += 2)
  291.          printmsg(6, "expect [%02d]:\t%s\nsend   [%02d]:\t%s",
  292.             i, flds[i], i + 1, flds[i + 1]);
  293.    }
  294.  
  295. /*--------------------------------------------------------------------*/
  296. /*               Determine if we want to call this host               */
  297. /*                                                                    */
  298. /*    The following if statement breaks down to:                      */
  299. /*                                                                    */
  300. /*       if host not successfully called this run and                 */
  301. /*             (  we are calling all hosts or                         */
  302. /*                we are calling this host or                         */
  303. /*                we are hosts with work and this host has work )     */
  304. /*       then call this host                                          */
  305. /*--------------------------------------------------------------------*/
  306.  
  307.    fwork = nil(FILE);
  308.    if ((hostp->hstatus != called) &&
  309.        (equal(Rmtname, "all") || equal(Rmtname, rmtname) ||
  310.         (equal(Rmtname, "any") &&
  311.         (scandir(rmtname,sendgrade) == XFER_REQUEST))))
  312.     {
  313.  
  314.       if (fwork != nil(FILE)) /* in case matched with scandir     */
  315.          fclose(fwork);
  316.  
  317.       scandir( NULL, sendgrade); /* Reset directory search as well   */
  318.  
  319. /*--------------------------------------------------------------------*/
  320. /*   We want to call the host; is it defined in our security table?   */
  321. /*--------------------------------------------------------------------*/
  322.  
  323.       securep = GetSecurity( hostp );
  324.       if ( securep == NULL )
  325.       {
  326.          printmsg(0,"getsystem: system \"%s\" not defined in "
  327.                     "PERMISSIONS file", hostp->hostname);
  328.          return CONN_INITIALIZE;
  329.       }
  330.  
  331.       memset( &remote_stats, 0, sizeof remote_stats);
  332.       return CONN_CHECKTIME;  /* startup this system */
  333.  
  334.    } /* if */
  335.    else
  336.       return CONN_INITIALIZE;    /* Look for next system to process   */
  337.  
  338. } /*getsystem*/
  339.  
  340. /*--------------------------------------------------------------------*/
  341. /*    s y s e n d                                                     */
  342. /*                                                                    */
  343. /*    End UUCP session negotiation                                    */
  344. /*--------------------------------------------------------------------*/
  345.  
  346. CONN_STATE sysend()
  347. {
  348.    char msg[80];
  349.  
  350.    wmsg("OOOOOO", TRUE);
  351.    rmsg(msg, TRUE, 5, sizeof msg);
  352.    wmsg("OOOOOO", TRUE);
  353.    ssleep(2);                 /* Wait for it to be transmitted       */
  354.  
  355.    return CONN_DROPLINE;
  356. } /*sysend*/
  357.  
  358. /*--------------------------------------------------------------------*/
  359. /*    w m s g                                                         */
  360. /*                                                                    */
  361. /*    write a ^P type msg to the remote uucp                          */
  362. /*--------------------------------------------------------------------*/
  363.  
  364. void wmsg(const char *msg, const boolean synch)
  365. {
  366.  
  367.    if (synch)
  368.       swrite("\0\020", 2);
  369.  
  370.    printmsg( 4, "==> %s%s", synch ? "^p" : "", msg );
  371.  
  372.    swrite(msg, strlen(msg));
  373.  
  374.    if (synch)
  375.       swrite("\0", 1);
  376.  
  377. } /*wmsg*/
  378.  
  379. /*--------------------------------------------------------------------*/
  380. /*    r m s g                                                         */
  381. /*                                                                    */
  382. /*    read a ^P msg from UUCP                                         */
  383. /*--------------------------------------------------------------------*/
  384.  
  385. int rmsg(char *msg, const boolean synch, unsigned int msgtime, int max_len)
  386. {
  387.    int i;
  388.    char ch = '?';       /* Initialize to non-zero value  */    /* ahd   */
  389.  
  390. /*--------------------------------------------------------------------*/
  391. /*                        flush until next ^P                         */
  392. /*--------------------------------------------------------------------*/
  393.  
  394.    if (synch == 1)
  395.    {
  396.       do {
  397.  
  398.          if (sread(&ch, 1, msgtime) < 1)
  399.          {
  400.             printmsg(2 ,"rmsg: Timeout waiting for sync");
  401.             return TIMEOUT;
  402.          } /* if */
  403.  
  404.       } while ((ch & 0x7f) != '\020');
  405.    }
  406.  
  407. /*--------------------------------------------------------------------*/
  408. /*   Read until timeout, next newline, or we fill the input buffer    */
  409. /*--------------------------------------------------------------------*/
  410.  
  411.    for (i = 0; (i < max_len) && (ch != '\0'); )
  412.    {
  413.       if (sread(&ch, 1, msgtime) < 1)
  414.       {
  415.          printmsg(1 ,"rmsg: Timeout reading message");
  416.          return TIMEOUT;
  417.       }
  418.  
  419. /*--------------------------------------------------------------------*/
  420. /*               Process backspaces if not in sync mode               */
  421. /*--------------------------------------------------------------------*/
  422.  
  423.       if ((synch != 1) &&
  424.           (ch != '\r') &&
  425.           (ch != '\n') &&
  426.           (ch != '\0') &&
  427.           iscntrl( ch ))
  428.       {
  429.          if ( i && ((ch == 0x7f) || (ch == '\b')))
  430.          {
  431.             i--;
  432.             if ( synch == 2 )
  433.                swrite( "\b \b", 3);
  434.          }
  435.          else {
  436.  
  437.             swrite( "\a", 1 );   /* Beep in response to invalid
  438.                                     cntrl characters, including
  439.                                     extra backspaces                 */
  440.          } /* else */
  441.  
  442.       } /* if */
  443.       else {                  /* else a normal character             */
  444.  
  445. /*--------------------------------------------------------------------*/
  446. /*             Echo the character if requested by caller              */
  447. /*--------------------------------------------------------------------*/
  448.  
  449.          if ( synch == 2 )
  450.             swrite( &ch, 1);
  451.  
  452.          ch &= 0x7f;
  453.          if (ch == '\r' || ch == '\n')
  454.             ch = '\0';
  455.          msg[i++] = ch;
  456.       } /* else */
  457.    }
  458.  
  459.    msg[max_len - 1] = '\0';
  460.    printmsg( 4, "<== %s%s",
  461.                 (synch == 1) ? "^p" : "",
  462.                 msg);
  463.    return strlen(msg);
  464.  
  465. } /*rmsg*/
  466.  
  467. /*--------------------------------------------------------------------*/
  468. /*    s t a r t u p _ s e r v e r                                     */
  469. /*                                                                    */
  470. /*    Exchange host and protocol information for a system we called   */
  471. /*--------------------------------------------------------------------*/
  472.  
  473. CONN_STATE startup_server(const char recvgrade )
  474. {
  475.    char msg[80];
  476.    char *s;
  477.  
  478.    hostp->hstatus = startup_failed;
  479.    hostp->via     = hostp->hostname;   // Save true hostname
  480.  
  481. /*--------------------------------------------------------------------*/
  482. /*    Handle the special case of '*' protocol, which is really our    */
  483. /*    NBS time setting support                                        */
  484. /*--------------------------------------------------------------------*/
  485.  
  486.    if (*protocols == '*')
  487.    {
  488.       if (nbstime())
  489.       {
  490.          hostp->hstatus = called;
  491.          time( &hostp->hstats->lconnect );
  492.       }
  493.  
  494.       return CONN_DROPLINE;
  495.    }
  496.  
  497. /*--------------------------------------------------------------------*/
  498. /*                      Begin normal processing                       */
  499. /*--------------------------------------------------------------------*/
  500.  
  501.    if (rmsg(msg, TRUE, M_startupTimeout, sizeof msg) == TIMEOUT)
  502.    {
  503.       printmsg(0,"Startup: Timeout for first message");
  504.       return CONN_TERMINATE;
  505.    }
  506.  
  507. /*--------------------------------------------------------------------*/
  508. /*              The first message must begin with Shere               */
  509. /*--------------------------------------------------------------------*/
  510.  
  511.    if (!equaln(msg,"Shere",5))
  512.    {
  513.       printmsg(0,"Startup: First message not Shere, was \"%s\"", msg);
  514.       return CONN_TERMINATE;
  515.    }
  516.  
  517. /*--------------------------------------------------------------------*/
  518. /*    The host can send either a simple Shere, or Shere=hostname;     */
  519. /*    we allow either.                                                */
  520. /*--------------------------------------------------------------------*/
  521.  
  522.    if ((msg[5] == '=') && !equaln(&msg[6], rmtname, HOSTLEN))
  523.    {
  524.       printmsg(0,"Startup: Wrong host %s, expected %s",
  525.                &msg[6], rmtname);
  526.       hostp->hstatus = wrong_host;
  527.       return CONN_TERMINATE; /* wrong host */              /* ahd */
  528.    }
  529.  
  530. /*--------------------------------------------------------------------*/
  531. /*    Setup our hello message with system name and optional debug     */
  532. /*    and call grade levels.                                          */
  533. /*--------------------------------------------------------------------*/
  534.  
  535.    sprintf(msg, "S%s", securep->myname );
  536.  
  537.    if ( bflag[F_SENDDEBUG] )
  538.       sprintf( msg + strlen(msg), " -x%d", debuglevel );
  539.  
  540.    if (recvgrade != ALL_GRADES)
  541.       sprintf( msg + strlen(msg), " -p%c -vgrade=%c",
  542.                   recvgrade, recvgrade );
  543.  
  544.    wmsg(msg, TRUE);
  545.  
  546. /*--------------------------------------------------------------------*/
  547. /*                  Second message is system is okay                  */
  548. /*--------------------------------------------------------------------*/
  549.  
  550.    if (rmsg(msg, TRUE, M_startupTimeout, sizeof msg) == TIMEOUT)
  551.    {
  552.       printmsg(0,"Startup: Timeout for second message");
  553.       return CONN_TERMINATE;
  554.    }
  555.  
  556.    if (!equaln(&msg[1], "OK", 2))
  557.    {
  558.       printmsg(0,"Unexpected second message: %s",&msg[1]);
  559.       return CONN_TERMINATE;
  560.    }
  561.  
  562. /*--------------------------------------------------------------------*/
  563. /*                Third message is protocol exchange                  */
  564. /*--------------------------------------------------------------------*/
  565.  
  566.    if (rmsg(msg, TRUE, M_startupTimeout, sizeof msg) == TIMEOUT)
  567.       return CONN_TERMINATE;
  568.  
  569.    if (*msg != 'P')
  570.    {
  571.       printmsg(0,"Unexpected third message: %s",&msg[1]);
  572.       return CONN_TERMINATE;
  573.    }
  574.  
  575. /*--------------------------------------------------------------------*/
  576. /*                      Locate a common procotol                      */
  577. /*--------------------------------------------------------------------*/
  578.  
  579.    s = strpbrk( protocols, &msg[1] );
  580.    if ( s == NULL )
  581.    {
  582.       printmsg(0,"Startup: No common protocol");
  583.       wmsg("UN", TRUE);
  584.       return CONN_TERMINATE; /* no common protocol */
  585.    }
  586.  
  587. /*--------------------------------------------------------------------*/
  588. /*       While the remote is waiting for us, update our status        */
  589. /*--------------------------------------------------------------------*/
  590.  
  591.    hostp->hstatus = inprogress;
  592.    hostp->hstats->lconnect = time( &remote_stats.lconnect );
  593.  
  594. /*--------------------------------------------------------------------*/
  595. /*              Tell the remote host the protocol to use              */
  596. /*--------------------------------------------------------------------*/
  597.  
  598.    sprintf(msg, "U%c", *s);
  599.    wmsg(msg, TRUE);
  600.  
  601.    setproto(*s);
  602.  
  603. /*--------------------------------------------------------------------*/
  604. /*    The connection is complete; report this and return to caller    */
  605. /*--------------------------------------------------------------------*/
  606.  
  607.    printmsg(0,"%s connected to %s: %ld bps, %c protocol, %c grade",
  608.          E_nodename, rmtname, (long) GetSpeed() , *s, recvgrade );
  609.  
  610.    return CONN_SERVER;
  611.  
  612. } /*startup_server*/
  613.  
  614. /*--------------------------------------------------------------------*/
  615. /*    s t a r t u p _ c l i e n t                                     */
  616. /*                                                                    */
  617. /*    Setup a host connection with a system which has called us       */
  618. /*--------------------------------------------------------------------*/
  619.  
  620. CONN_STATE startup_client( char *sendgrade )
  621. {
  622.    char plist[20];
  623.    char msg[80];
  624.    int xdebug = debuglevel;
  625.    char *sysname = rmtname;
  626.    Proto *tproto;
  627.    char *s;
  628.    char *flds[10];
  629.    int  kflds,i;
  630.    char grade = ALL_GRADES;
  631.  
  632. /*--------------------------------------------------------------------*/
  633. /*    Challange the host calling in with the name defined for this    */
  634. /*    login (if available) otherwise our regular node name.  (It's    */
  635. /*    a valid session if the securep pointer is NULL, but this is     */
  636. /*    trapped below in the call to ValidateHost()                     */
  637. /*--------------------------------------------------------------------*/
  638.  
  639.    sprintf(msg, "Shere=%s", securep == NULL ?
  640.                               E_nodename : securep->myname );
  641.    wmsg(msg, TRUE);
  642.  
  643.    if (rmsg(msg, TRUE, M_startupTimeout, sizeof msg) == TIMEOUT)
  644.       return CONN_TERMINATE;
  645.  
  646.    printmsg(2, "1st msg from remote = %s", msg);
  647.  
  648. /*--------------------------------------------------------------------*/
  649. /*             Parse additional flags from remote system              */
  650. /*--------------------------------------------------------------------*/
  651.  
  652.    kflds = getargs(msg,flds);
  653.    strcpy(sysname,&flds[0][1]);
  654.  
  655.    for (i=1; i < kflds; i++)
  656.    {
  657.       if (flds[i][0] != '-')
  658.          printmsg(0,"Invalid argument \"%s\" from system %s",
  659.                     flds[i],
  660.                     sysname);
  661.       else
  662.          switch(flds[i][1])
  663.          {
  664.             case 'Q' :             /* Ignore the remote sequence number   */
  665.                break;
  666.  
  667.             case 'x' :
  668.                if ( bflag[ F_HONORDEBUG ] )
  669.                   sscanf(flds[i], "-x%d", &xdebug);
  670.                break;
  671.  
  672.             case 'p' :
  673.                sscanf(flds[i], "-p%c", &grade);
  674.                break;
  675.  
  676.             case 'v' :
  677.                sscanf(flds[i], "-vgrade=%c", &grade);
  678.                break;
  679.  
  680.             default  :
  681.                printmsg(0,"Invalid argument \"%s\" from system %s",
  682.                           flds[i],
  683.                           sysname);
  684.                break;
  685.          } /* switch */
  686.    } /* for */
  687.  
  688.    *sendgrade = min(grade,*sendgrade);
  689.  
  690. /*--------------------------------------------------------------------*/
  691. /*                Verify the remote host name is good                 */
  692. /*--------------------------------------------------------------------*/
  693.  
  694.    hostp = checkreal( sysname );
  695.  
  696.    if ( hostp == BADHOST )
  697.    {
  698.       if (E_anonymous != NULL)
  699.       {
  700.          hostp = checkreal( ANONYMOUS_HOST );      /* Find dummy entry */
  701.  
  702.          if ( hostp == BADHOST )       /* Was it there?              */
  703.             panic();                   /* No --> Drop wing, run in
  704.                                           circles like sky is falling*/
  705.  
  706.          if (!checktime( E_anonymous )) /* Good time to call?         */
  707.          {
  708.             wmsg("RWrong time for anonymous system",TRUE);
  709.             printmsg(0,"Wrong time for anonymous system \"%s\"",sysname);
  710.          }  /* if */
  711.  
  712.          if ( !LockSystem( sysname , B_UUCICO ))
  713.          {
  714.             wmsg("RLCK",TRUE);   /* Odd, we locked anonymous system? */
  715.             return CONN_TERMINATE;
  716.          }
  717.  
  718.          hostp->via = newstr( sysname );
  719.          sysname = ANONYMOUS_HOST;
  720.  
  721.       }    /* if (E_anonymous != NULL) */
  722.       else {
  723.          wmsg("RYou are unknown to me",TRUE);
  724.          printmsg(0,"startup: Unknown host \"%s\"", sysname);
  725.          return CONN_TERMINATE;
  726.       } /* else */
  727.    } /* if ( hostp == BADHOST ) */
  728.    else if ( LockSystem( hostp->hostname , B_UUCICO ))
  729.       hostp->via = hostp->hostname;
  730.    else {
  731.       wmsg("RLCK",TRUE);
  732.       return CONN_TERMINATE;
  733.    } /* else */
  734.  
  735. /*--------------------------------------------------------------------*/
  736. /*                   Correct host for this user id?                   */
  737. /*--------------------------------------------------------------------*/
  738.  
  739.    if ( !ValidateHost( sysname ))
  740.                                           /* Wrong host for user? */
  741.    {                                      /* Yes --> Abort        */
  742.       wmsg("RLOGIN",TRUE);
  743.       printmsg(0,"startup: Access rejected for host \"%s\"", sysname);
  744.       hostp->hstatus = wrong_host;
  745.       return CONN_TERMINATE;
  746.    } /* if */
  747.  
  748.    strcpy(rmtname, hostp->hostname);      /* Make sure we use the
  749.                                              full host name       */
  750.  
  751. /*--------------------------------------------------------------------*/
  752. /*                If we must call the user back, do so                */
  753. /*--------------------------------------------------------------------*/
  754.  
  755.    if (securep->callback)
  756.    {
  757.       wmsg("RCB",TRUE);
  758.       hostp->hstatus = callback_req;
  759.       return CONN_TERMINATE;  /* Really more complex than this       */
  760.    }
  761.  
  762. /*--------------------------------------------------------------------*/
  763. /*                     Set the local debug level                      */
  764. /*--------------------------------------------------------------------*/
  765.  
  766.    if ( xdebug > debuglevel )
  767.    {
  768.       debuglevel = xdebug;
  769.       printmsg(0, "Debuglevel set to %d by remote", debuglevel);
  770.    }
  771.  
  772. /*--------------------------------------------------------------------*/
  773. /*                     Build local protocol list                      */
  774. /*--------------------------------------------------------------------*/
  775.  
  776.    s = plist;
  777.    for (tproto = Protolst; tproto->type != '\0' ; tproto++)
  778.    {
  779.       if ( IsNetwork() || !tproto->network )
  780.          *s++ = tproto->type;
  781.    }
  782.  
  783.    *s = '\0';                 /* Terminate our string                */
  784.  
  785. /*--------------------------------------------------------------------*/
  786. /*              The host name is good; get the protocol               */
  787. /*--------------------------------------------------------------------*/
  788.  
  789.    wmsg("ROK", TRUE);
  790.  
  791.    sprintf(msg, "P%s", plist);
  792.    wmsg(msg, TRUE);
  793.  
  794.    if (rmsg(msg, TRUE, M_startupTimeout, sizeof msg) == TIMEOUT)
  795.       return CONN_TERMINATE;
  796.  
  797.    if (msg[0] != 'U')
  798.    {
  799.       printmsg(0,"Unexpected second message: %s", msg);
  800.       return CONN_TERMINATE;
  801.    }
  802.  
  803.    if (strchr(plist, msg[1]) == nil(char))
  804.    {
  805.       printmsg(0,"startup: Host %s does not support our protocols",
  806.             rmtname );
  807.       return CONN_TERMINATE;
  808.    }
  809.  
  810.    setproto(msg[1]);
  811.  
  812. /*--------------------------------------------------------------------*/
  813. /*            Report that we connected to the remote host             */
  814. /*--------------------------------------------------------------------*/
  815.  
  816.    printmsg(0,"%s called by %s: %ld bps, %c protocol, %c grade",
  817.          E_nodename,
  818.          hostp->via,
  819.          (long) GetSpeed(),
  820.          msg[1],
  821.          *sendgrade );
  822.  
  823.    if ( hostp == BADHOST )
  824.       panic();
  825.  
  826.    hostp->hstatus = inprogress;
  827.    hostp->hstats->lconnect = time( &remote_stats.lconnect );
  828.  
  829.    return CONN_CLIENT;
  830.  
  831. } /*startup_client*/
  832.  
  833. /*--------------------------------------------------------------------*/
  834. /*    s e t p r o t o                                                 */
  835. /*                                                                    */
  836. /*    set the protocol to be used                                     */
  837. /*--------------------------------------------------------------------*/
  838.  
  839. static void setproto(char wanted)
  840. {
  841.    Proto *tproto;
  842.  
  843.    for (tproto = Protolst;
  844.       tproto->type != '\0' && tproto->type != wanted;
  845.       tproto++) {
  846.       printmsg(3, "setproto: wanted '%c', have '%c'", wanted, tproto->type);
  847.    }
  848.  
  849.    if (tproto->type == '\0') {
  850.       printmsg(0, "setproto: You said I have protocol '%c' but I cant find it!",
  851.             wanted);
  852.       panic();
  853.    }
  854.  
  855.    printmsg(3, "setproto: wanted '%c', have '%c'", wanted, tproto->type);
  856.  
  857.    getpkt  = tproto->getpkt;
  858.    sendpkt = tproto->sendpkt;
  859.    openpk  = tproto->openpk;
  860.    closepk = tproto->closepk;
  861.    rdmsg   = tproto->rdmsg;
  862.    wrmsg   = tproto->wrmsg;
  863.    eofpkt  = tproto->eofpkt;
  864.    filepkt = tproto->filepkt;
  865.  
  866. } /*setproto*/
  867.  
  868. /*--------------------------------------------------------------------*/
  869. /*    s c a n d i r                                                   */
  870. /*                                                                    */
  871. /*    Scan spooling directory for C.* files for the remote host       */
  872. /*    (rmtname)                                                       */
  873. /*--------------------------------------------------------------------*/
  874.  
  875. XFER_STATE scandir(char *remote, const char grade )
  876. {
  877.    static DIR *dirp = NULL;
  878.    static char *SaveRemote = NULL;
  879.    static char remotedir[FILENAME_MAX];
  880.  
  881.    struct direct *dp;
  882.  
  883. /*--------------------------------------------------------------------*/
  884. /*          Determine if we must restart the directory scan           */
  885. /*--------------------------------------------------------------------*/
  886.  
  887.    if (fwork != NULL )
  888.    {
  889.       fclose( fwork );
  890.       fwork = NULL;
  891.    }
  892.  
  893.    if ( (remote == NULL) || ( SaveRemote == NULL ) ||
  894.         !equaln(remote, SaveRemote, sizeof SaveRemote - 1 ) )
  895.    {
  896.       if ( SaveRemote != NULL ) /* Clean up old directory? */
  897.       {                          /* Yes --> Do so           */
  898.          closedir(dirp);
  899.          dirp = NULL;
  900.          SaveRemote = NULL;
  901.       } /* if */
  902.  
  903.       if ( remote == NULL )      /* Clean up only, no new search? */
  904.          return XFER_NOLOCAL;    /* Yes --> Return to caller      */
  905.  
  906.       sprintf(remotedir,"%s/%.8s/C", E_spooldir, remote);
  907.       if ((dirp = opendir(remotedir)) == nil(DIR))
  908.       {
  909.          printmsg(2, "scandir: couldn't opendir() %s", remotedir);
  910.          return XFER_NOLOCAL;
  911.       } /* if */
  912.  
  913.       SaveRemote = newstr( remote );
  914.                               /* Flag we have an active search    */
  915.  
  916.    } /* if */
  917.  
  918. /*--------------------------------------------------------------------*/
  919. /*              Look for the next file in the directory               */
  920. /*--------------------------------------------------------------------*/
  921.  
  922.    while ((dp = readdir(dirp)) != nil(struct direct))
  923.    {
  924.       sprintf(workfile, "%s/%s", remotedir, dp->d_name);
  925.  
  926.       if ( HostGrade( workfile, remote ) > grade )
  927.          printmsg(5, "scandir: skipped \"%s\" (grade %c not met)",             workfile,
  928.                       grade );
  929.       else if ((fwork = FOPEN(workfile, "r",TEXT_MODE)) == nil(FILE))
  930.       {
  931.          printmsg(0,"scandir: open failed for %s",workfile);
  932.          SaveRemote = NULL;
  933.          return XFER_ABORT;   /* Very bad, since we just read its
  934.                                  directory entry!                 */
  935.       }
  936.       else {
  937.          setvbuf( fwork, NULL, _IONBF, 0);
  938.          printmsg(5, "scandir: matched \"%s\"",workfile);
  939.          return XFER_REQUEST; /* Return success                   */
  940.       }
  941.  
  942.    } /* while */
  943.  
  944. /*--------------------------------------------------------------------*/
  945. /*     No hit; clean up after ourselves and return to the caller      */
  946. /*--------------------------------------------------------------------*/
  947.  
  948.    printmsg(5, "scandir: \"%s\" not matched", remotedir);
  949.    closedir(dirp);
  950.    dirp = NULL;
  951.    SaveRemote = NULL;
  952.    return XFER_NOLOCAL;
  953.  
  954. } /*scandir*/
  955.  
  956. /*--------------------------------------------------------------------*/
  957. /*    H o s t G r a d e                                               */
  958. /*                                                                    */
  959. /*    Return host grade of a call file                                */
  960. /*--------------------------------------------------------------------*/
  961.  
  962. static char HostGrade( const char *fname, const char *remote )
  963. {
  964.  
  965.    char tempname[FILENAME_MAX];
  966.    size_t len = strlen( remote );
  967.  
  968.    exportpath( tempname, fname, remote );
  969.  
  970.    if ( len > HOSTLEN )
  971.       len = HOSTLEN;
  972.  
  973.    return tempname[len + 2 ];
  974.  
  975. } /* HostGrade */
  976.  
  977. /*--------------------------------------------------------------------*/
  978. /*    C a l l W i n d o w                                             */
  979. /*                                                                    */
  980. /*    Determine if we can call a system                               */
  981. /*--------------------------------------------------------------------*/
  982.  
  983. boolean CallWindow( const char callgrade )
  984. {
  985.  
  986. /*--------------------------------------------------------------------*/
  987. /*      Determine if the window for calling this system is open       */
  988. /*--------------------------------------------------------------------*/
  989.  
  990.    if ( !callgrade && equal(flds[FLD_CCTIME],"Never" ))
  991.    {
  992.       hostp->hstatus = wrong_time;
  993.       return FALSE;
  994.    }
  995.  
  996. /*--------------------------------------------------------------------*/
  997. /*    Check the time of day and whether or not we should call now.    */
  998. /*                                                                    */
  999. /*    If calling a system to set the clock and we determine the       */
  1000. /*    system clock is bad (we fail the sanity check of the last       */
  1001. /*    connected a host to being in the future), then we ignore the    */
  1002. /*    time check field.                                               */
  1003. /*--------------------------------------------------------------------*/
  1004.  
  1005.    if (!callgrade)
  1006.    {
  1007.       if ((*flds[FLD_PROTO] != '*') ||       /* Not setting clock?   */
  1008.           ((hostp->hstats->ltime >  630720000L )))
  1009.                                              /* Clock okay?          */
  1010.       {                                      /* Yes--> Return        */
  1011.          hostp->hstatus = wrong_time;
  1012.          time(&hostp->hstats->ltime);  /* Save time of last attempt to call   */
  1013.          return FALSE;
  1014.       }
  1015.    } /* if */
  1016.  
  1017. /*--------------------------------------------------------------------*/
  1018. /*       We pass the time check                                       */
  1019. /*--------------------------------------------------------------------*/
  1020.  
  1021.    return TRUE;
  1022.  
  1023. } /* CallWindow */
  1024.